import * as bfun from '../../core/fbyte.js';
/**
 * 专门用于编码 (用树结构编码)
 * 仅支持 uint8array key
 */
//根节点 是0层
//每往下 加1层
const BNode = {
	newCreate(父, 层, b, code) {
		let self = {
			pnd:父,
			pass: 0, //经过权重
			level: 层 || 0,
			child: new Map(), //子节点
			code, //id		
			b
		};
		return self;
	},
	up(node, callback) {
		if (node) {
			callback(node)
			if (node.pnd) {
				BNode.up(node.pnd, callback);
			}
		}
	},
	//向下遍历公共函数
	down(node, callback) {
		if (node == null) return;
		let ta = this;
		//console.log(node)
		node.child.forEach(function(nd, b, map) {
			//vue 扩展对象的属性 extend 导致的问题
			if (nd == null) return;
			let flag = callback(node, nd, b);
			if (flag) return;
			ta.down(nd, callback);
		});
	},
	/**
	 * 插入固定长度的 bytes 改变树的结构
	 * @param {Object} node  树根节点 root 是第0层
	 * @param {Object} bytes  插入不限定长度的字节
	 * @param {Object} level  表示节点在第几level  从第一层开始
	 */
	setn(node, bytes, level) {
		let ta = this;
		//为空跳过	
		if (bytes == null || bytes.length == 0) return;
		level = level || 1;
		if (level > bytes.length) return;
		let b0 = bytes[level - 1];
		//console.log(b0)
		//如果节点为空创建一个
		let nd = node.child.get(b0);
		if (nd == null) {
			nd = ta.newCreate(node, level, b0);
			node.child.set(b0, nd);
		}
		//创建子节点
		nd.pass++;
		//继续下钻
		if (bytes.length > level) {
			level++;
			return ta.setn(nd, bytes, level);
		} else
			return nd;
	},
	
	sort_id(node){
		let n=0;
		function sort(node){
			if (node == null) return;
			let ta = this;
			//console.log(node)
			if (node.child.size == 0){
				node.code=++n;
			}else{			
				var arrayObj = Array.from(node.child);
				arrayObj.sort(function(a,b){return a[0]-b[0]})		
				node.child = new Map(arrayObj.map(i => [i[0], i[1]]));
				node.child.forEach(function(nd, b, map) {
					sort(nd);
				});
			}
		}
		sort(node);
		return n;
	},
	sort_kv(node){
		let mp=new Map();
		let n=0;
		let ta=this;
		function getBs(node){
			let li=[]
			ta.up(node,function(nd){
				li.unshift(nd.b);
			});
			return li;
		}
		function sort(node){
			if (node == null) return;
			let ta = this;
			//console.log(node)
			if (node.child.size == 0){
				mp.set(++n,getBs(node));
			}else{			
				var arrayObj = Array.from(node.child);
				arrayObj.sort(function(a,b){return a[0]-b[0]})		
				node.child = new Map(arrayObj.map(i => [i[0], i[1]]));
				node.child.forEach(function(nd, b, map) {
					sort(nd);
				});
			}
		}
		sort(node);
		return mp;
	},
	/*
	插入不固定的长度
	如果树节点已经存在,挂在树节点下面,
	如果不存在,添加到父节点后面
	*/
	putNofixed(root, bytes) {
		let id = 1;
		let ta = this;

		function add(nd1, bs, level) {
			if (bs == null || bs.length == 0) return;
			level = level || 1;
			let b0 = bs[0];
			bs = bs.subarray(1);
			let nd2 = nd1.child.get(b0);
			if (nd2 == null) {
				nd2 = ta.newCreate(nd1, level, b0, id++);
				nd1.child.set(b0, nd2);
				add(root, bs, 0);
			} else {
				nd2.pass++;
				add(nd2, bs, ++level);
			}
		}
		add(root, bytes, 0);
	},
	//以下两个方法 适用于map场合
	/**
	 * 
	 * @param {Object} root 树根节点
	 * @param {Object} bytes  插入不限定长度的字节
	 * @param {Object} value  设置末尾节点附加值
	 */
	testput(root, bytes, value) {
		if (root == null || bytes == null || bytes.length == 0) return null;
		let b0 = bytes[0];
		let nd = root.child.get(b0);
		if (nd == null) {
			nd = BNode.newCreate(root)
			root.child.set(b0, nd);
		}
		if (bytes.length == 1) {
			nd.value = value;
		} else {
			this.put(nd, bytes.subarray(1));
		}
	},
	//从树指定节点开始 找到字节数据匹配的节点
	get(node, key) {
		let ta = this;
		if (key == null || key.length == 0) return node;
		if (node && node.child.size > 0) {
			let nd = node.child.get(key[0]);
			if (nd == null) return null;
			return ta.get(nd, key.subarray(1));
		}
	},
	//遍历输出节点
	view(root) {
		this.down(root, function(pnd, nd, key) {
			if (nd)
				console.log(pnd && pnd.b, '--', nd.b, nd.level, nd.code)
		});
	},
	//树的层必须大于1,否则直接输出树
	tree_list(root) {
		let dict = []; //[元素,子节点个数]
		let ta = this;
		let 最大层 = 0;

		function add1(node) {
			let n = node.level;
			if (dict[n - 1] == null)
				dict[n - 1] = [];
			最大层 = Math.max(最大层, n);
			dict[n - 1].push([node.b, node.child.size]);
		}
		ta.down(root, function(pnd, nd, k) {
			if (nd.level > 0) {
				add1(nd);
			}
		});
		return [最大层, dict];
	},
	//树list 转成 uint8array
	list_ui8(params) {
		let dict = params[1];
		let ta = this;
		let 最大层 = params[0];
		let n = 0;
		let arr = [最大层];//不超过255 一个字节够了
		for (let l = 最大层 - 1; l >= 0; l--) {
			//console.log(l, dict[l]);
			//遍历每层
			let ar = dict[l];
			let maxlen = ar.length;
			arr.push(bfun.intToByte4(maxlen));
			arr.push(ar.flat());
		};
		return new Uint8Array(arr.flat());
	},
	//把uint8array 转成树
	ui8_tree(uilist,字长) {
		let ta = this;
		let rep_id2= (字长 == 1) ?function(bytes,off){return bytes[off];} : (字长 == 2) ?bfun.byte2ToShort :bfun.byte4ToInt;
				
		function mount(narr1, narr2) {
			//把narr2 挂到 narr1下面			
			let j = 0,
				k = 0;
			let nd;
			while (0 < narr2.length) {
				if (k == 0 && j < narr1.length) {
					nd = narr1[j];
					k = nd.code; //子元素个数
					j++;
				}
				if (k > 0) {
					narr2[0].pnd=nd;
					nd.child.set(narr2[0].b, narr2[0]);
					narr2.shift();
					k--;
				}
			}
			//console.log(narr1,narr2);
		}
		//解读每层,组装成树
		function step1(list, 层, narr2) {
			//console.log(list.length,list.toString(),narr2&&narr2.toString());
			let k = 0; //list 数组的偏移量
			let len =bfun.byte4ToInt(list, k);//每层一共多少节点
			let n = len * 2;
			k += 4;
			let arr = list.subarray(k, k + n);
			k += n;
			var narr1 = [];
			for (let i = 0; i < n; i += 2) {
				//节点b,子节点个数
				let nd = ta.newCreate(null, 层, arr[i], arr[i + 1]);
				narr1.push(nd);
			}
			if (narr1 != null && narr1.length > 0 && narr2 != null) {
				mount(narr1, narr2);
			}
			list = list.subarray(k);
			if (list.length > 0)
				return step1(list, 层 - 1, narr1);
			else
				return narr1;
		}
		//console.log(uilist)
		let maxlevel = uilist[0];
		let root = ta.newCreate();
		let arr0 = step1(uilist.subarray(1), maxlevel);
		for (let i = 0; i < arr0.length; i++) {
			root.child.set(arr0[i].b, arr0[i]);
		}
		return root;
	}
};


export default BNode;
